/**
 * Copyright (C) 2009 - 2013 SC 4ViewSoft SRL
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.achartengine;

import org.achartengine.chart.AbstractChart;
import org.achartengine.chart.RoundChart;
import org.achartengine.chart.XYChart;
import org.achartengine.model.Point;
import org.achartengine.model.SeriesSelection;
import org.achartengine.renderer.DefaultRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.tools.FitZoom;
import org.achartengine.tools.PanListener;
import org.achartengine.tools.Zoom;
import org.achartengine.tools.ZoomListener;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.DimensFloat;
import ohos.agp.utils.Rect;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;

/**
 * The view that encapsulates the graphical chart.
 */
public class GraphicalView
        extends Component implements Component.DrawTask {

    /**
     * The chart to be drawn.
     */
    private AbstractChart mChart;
    /**
     * The chart renderer.
     */
    private DefaultRenderer mRenderer;
    /**
     * The view bounds.
     */
    private Rect mRect = new Rect();
    /**
     * The user interface thread handler.
     */
    private EventHandler mHandler;
    /**
     * The zoom buttons rectangle.
     */
    private Rect mZoomR = new Rect();

    /**
     * The zoom buttons background color.
     */
    private static final int ZOOM_BUTTONS_COLOR = Color.argb(175, 150, 150, 150);
    /**
     * The zoom in tool.
     */
    private Zoom mZoomIn;
    /**
     * The zoom out tool.
     */
    private Zoom mZoomOut;
    /**
     * The fit zoom tool.
     */
    private FitZoom mFitZoom;
    /**
     * The paint to be used when drawing the chart.
     */
    private Paint mPaint = new Paint();
    /**
     * The touch handler.
     */
    private ITouchHandler mTouchHandler;
    /**
     * The old x coordinate.
     */
    private float oldX;
    /**
     * The old y coordinate.
     */
    private float oldY;
    /**
     * If the graphical view is drawn.
     */
    private boolean mDrawn;
    HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0, "GraphicalView");

    /**
     * Creates a new graphical view.
     *
     * @param context the context
     * @param chart   the chart to be drawn
     */
    public GraphicalView(Context context, AbstractChart chart) {
        super(context);
        mChart = chart;
        mHandler = new EventHandler(EventRunner.getMainEventRunner());
        if (mChart instanceof XYChart) {
            mRenderer = ((XYChart) mChart).getRenderer();
        } else {
            mRenderer = ((RoundChart) mChart).getRenderer();
        }
//        if (mRenderer.isZoomButtonsVisible()) {
//            try {
//                ohos.global.resource.RawFileEntry rawFileEntry = context.getResourceManager().getRawFileEntry("resources/rawfile/zoom_in.png");
//                ImageSource imageSource = ImageSource.create(
//                        rawFileEntry.openRawFile(), new ImageSource.SourceOptions());
//                zoomInImage = imageSource.createPixelmap(new ImageSource.DecodingOptions());
//
//                ohos.global.resource.RawFileEntry rawFileEntry2 = context.getResourceManager().getRawFileEntry("resources/rawfile/zoom_out.png");
//                ImageSource imageSource2 = ImageSource.create(
//                        rawFileEntry2.openRawFile(), new ImageSource.SourceOptions());
//                zoomOutImage = imageSource2.createPixelmap(new ImageSource.DecodingOptions());
//
//                ohos.global.resource.RawFileEntry rawFileEntry3 = context.getResourceManager().getRawFileEntry("resources/rawfile/zoom-1.png");
//                ImageSource imageSource3 = ImageSource.create(
//                        rawFileEntry3.openRawFile(), new ImageSource.SourceOptions());
//                fitZoomImage = imageSource3.createPixelmap(new ImageSource.DecodingOptions());
//            } catch (IOException e) {
//                HiLog.error(label,"%{public}s",e.toString());
//            }
//
//        }

        if (mRenderer instanceof XYMultipleSeriesRenderer
                && ((XYMultipleSeriesRenderer) mRenderer).getMarginsColor() == XYMultipleSeriesRenderer.NO_COLOR) {
            ((XYMultipleSeriesRenderer) mRenderer).setMarginsColor(-16777216);
        }
        if (mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()
                || mRenderer.isExternalZoomEnabled()) {
            mZoomIn = new Zoom(mChart, true, mRenderer.getZoomRate());
            mZoomOut = new Zoom(mChart, false, mRenderer.getZoomRate());
            mFitZoom = new FitZoom(mChart);
        }
//        int version = 7;
//        try {
//      version = Integer.valueOf(Build.VERSION.SDK);
//        } catch (Exception e) {
//            // do nothing
//        }
//    if (version < 7) {
//      mTouchHandler = new TouchHandlerOld(this, mChart);
//    } else {
        mTouchHandler = new TouchHandler(this, mChart);
        setTouchEventListener(new TouchEventListener() {
            @Override
            public boolean onTouchEvent(Component component, TouchEvent event) {
                MmiPoint point = event.getPointerPosition(event.getIndex());
                if (event.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
                    // save the x and y so they can be used in the click and long press
                    // listeners
                    oldX = point.getX();
                    oldY = point.getY();
                }
                if (mRenderer != null && mDrawn && (mRenderer.isPanEnabled() || mRenderer.isZoomEnabled())) {
                    if (mTouchHandler.handleTouch(event)) {
                    }
                }
                return true;
            }
        });
//    }
    }

    //
//  /**
//   * Returns the current series selection object.
//   *
//   * @return the series selection
//   */
    public SeriesSelection getCurrentSeriesAndPoint() {
        return mChart.getSeriesAndPointForScreenCoordinate(new Point(oldX, oldY));
    }


    /**
     * Returns the drawn state of the chart.
     *
     * @return the drawn state of the chart
     */
    public boolean isChartDrawn() {
        return mDrawn;
    }

    /**
     * Transforms the currently selected screen point to a real point.
     *
     * @param scale the scale
     * @return the currently selected real point
     */
    public double[] toRealPoint(int scale) {
        if (mChart instanceof XYChart) {
            XYChart chart = (XYChart) mChart;
            return chart.toRealPoint(oldX, oldY, scale);
        }
        return null;
    }

    public AbstractChart getChart() {
        return mChart;
    }


//  @Override
//  protected void onDraw(Canvas canvas) {
//    super.onDraw(canvas);
//    canvas.getClipBounds(mRect);
//    int top = mRect.top;
//    int left = mRect.left;
//    int width = mRect.width();
//    int height = mRect.height();
//    if (mRenderer.isInScroll()) {
//      top = 0;
//      left = 0;
//      width = getMeasuredWidth();
//      height = getMeasuredHeight();
//    }
//    mChart.draw(canvas, left, top, width, height, mPaint);
//    if (mRenderer != null && mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()) {
//      mPaint.setColor(ZOOM_BUTTONS_COLOR);
//      zoomSize = Math.max(zoomSize, Math.min(width, height) / 7);
//      mZoomR.set(left + width - zoomSize * 3, top + height - zoomSize * 0.775f, left + width, top
//          + height);
//      canvas.drawRoundRect(mZoomR, zoomSize / 3, zoomSize / 3, mPaint);
//      float buttonY = top + height - zoomSize * 0.625f;
//      canvas.drawBitmap(zoomInImage, left + width - zoomSize * 2.75f, buttonY, null);
//      canvas.drawBitmap(zoomOutImage, left + width - zoomSize * 1.75f, buttonY, null);
//      canvas.drawBitmap(fitZoomImage, left + width - zoomSize * 0.75f, buttonY, null);
//    }
//    mDrawn = true;
//  }

    /**
     * Sets the zoom rate.
     *
     * @param rate the zoom rate
     */
    public void setZoomRate(float rate) {
        if (mZoomIn != null && mZoomOut != null) {
            mZoomIn.setZoomRate(rate);
            mZoomOut.setZoomRate(rate);
        }
    }
//

    /**
     * Do a chart zoom in.
     */
    public void zoomIn() {
        if (mZoomIn != null) {
            mZoomIn.apply(Zoom.ZOOM_AXIS_XY);
            repaint();
        }
    }

    /**
     * Do a chart zoom out.
     */
    public void zoomOut() {
        if (mZoomOut != null) {
            mZoomOut.apply(Zoom.ZOOM_AXIS_XY);
            repaint();
        }
    }

    /**
     * Do a chart zoom reset / fit zoom.
     */
    public void zoomReset() {
        if (mFitZoom != null) {
            mFitZoom.apply();
            mZoomIn.notifyZoomResetListeners();
            repaint();
        }
    }

    /**
     * Adds a new zoom listener.
     *
     * @param listener zoom listener
     * @param onButtons onButtons
     * @param onPinch onPinch
     */
    public void addZoomListener(ZoomListener listener, boolean onButtons, boolean onPinch) {
        if (onButtons) {
            if (mZoomIn != null) {
                mZoomIn.addZoomListener(listener);
                mZoomOut.addZoomListener(listener);
            }
        }
        if (onPinch) {
            mTouchHandler.addZoomListener(listener);
        }
    }

    /**
     * Removes a zoom listener.
     *
     * @param listener zoom listener
     */
    public synchronized void removeZoomListener(ZoomListener listener) {
        if (mZoomIn != null) {
            mZoomIn.removeZoomListener(listener);
            mZoomOut.removeZoomListener(listener);
        }
        mTouchHandler.removeZoomListener(listener);
    }

    /**
     * Adds a new pan listener.
     *
     * @param listener pan listener
     */
    public void addPanListener(PanListener listener) {
        mTouchHandler.addPanListener(listener);
    }

    /**
     * Removes a pan listener.
     *
     * @param listener pan listener
     */
    public void removePanListener(PanListener listener) {
        mTouchHandler.removePanListener(listener);
    }

    protected RectFloat getZoomRectangle() {
        return new RectFloat(mZoomR);
    }

//  @Override
//  public boolean onTouchEvent(MotionEvent event) {
//    if (event.getAction() == MotionEvent.ACTION_DOWN) {
//      // save the x and y so they can be used in the click and long press
//      // listeners
//      oldX = event.getX();
//      oldY = event.getY();
//    }
//    if (mRenderer != null && mDrawn && (mRenderer.isPanEnabled() || mRenderer.isZoomEnabled())) {
//      if (mTouchHandler.handleTouch(event)) {
//        return true;
//      }
//    }
//    return super.onTouchEvent(event);
//  }

    /**
     * Schedule a view content repaint.
     */
    public void repaint() {
        mHandler.postTask(new Runnable() {
            public void run() {
                HiLog.info(label, "%{public}s", "repaint");
                invalidate();
            }
        });
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        HiLog.info(label, "%{public}s", "onDraw");
        DimensFloat componentSize = getComponentSize();
        int sizeXToInt = componentSize.getSizeXToInt();
        int sizeYToInt = componentSize.getSizeYToInt();
        canvas.getDeviceClipBounds(mRect);
        int top = mRect.top;
        int left = mRect.left;
        int width = mRect.getWidth();
        int height = mRect.getHeight();
        if (mRenderer.isInScroll()) {
            top = 0;
            left = 0;
            width = component.getWidth();
            height = component.getHeight();
        }
        mPaint.setColor(new Color(-1349085546));
        mChart.draw(canvas, left, top, sizeXToInt, sizeYToInt, mPaint);
        System.out.println("=====hosmRect===="+left+"-"+top+"-"+width+"-"+height);
//        if (mRenderer != null && mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()) {
//            mPaint.setColor(new Color(ZOOM_BUTTONS_COLOR));
//            zoomSize = Math.max(zoomSize, Math.min(width, height) / 7);
//            mZoomR.set(left + width - zoomSize * 3, (int) (top + height - zoomSize * 0.775f), left + width, top
//                    + height);
//            canvas.drawRoundRect(new RectFloat(mZoomR), zoomSize / 3, zoomSize / 3, mPaint);
//            float buttonY = top + height - zoomSize * 0.625f;

//                canvas.drawPixelMapHolder(new PixelMapHolder(zoomInImage), left + width - zoomSize * 2.75f, buttonY, mPaint);
//                canvas.drawPixelMapHolder(new PixelMapHolder(zoomOutImage), left + width - zoomSize * 1.75f, buttonY, mPaint);
//                canvas.drawPixelMapHolder(new PixelMapHolder(fitZoomImage), left + width - zoomSize * 0.75f, buttonY, mPaint);
//        }
        mDrawn = true;
    }

    /**
     * Schedule a view content repaint, in the specified rectangle area.
     *
     * @param left the left position of the area to be repainted
     * @param top the top position of the area to be repainted
     * @param right the right position of the area to be repainted
     * @param bottom the bottom position of the area to be repainted
     */
//  public void repaint(final int left, final int top, final int right, final int bottom) {
//    mHandler.postTask(new Runnable() {
//      public void run() {
//        invalidate(left, top, right, bottom);
//      }
//    });
//  }

    /**
     * Saves the content of the graphical view to a bitmap.
     *
     * @return the bitmap
     */
//  public Bitmap toBitmap() {
//    setDrawingCacheEnabled(false);
//    if (!isDrawingCacheEnabled()) {
//      setDrawingCacheEnabled(true);
//    }
//    if (mRenderer.isApplyBackgroundColor()) {
//      setDrawingCacheBackgroundColor(mRenderer.getBackgroundColor());
//    }
//    setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
//    return getDrawingCache(true);
//  }

}